This site is supported by donations to The OEIS Foundation.
Complete non-self-adjacent paths:Program
From OeisWiki
/*
Filename: CNSAP.cpp
Purpose: To calculate all complete non-self-adjacent paths (CNSAPs) in square and cubic lattices bounded by various sizes of rectangle and
rectangular cuboid respectively.
Build info: The program builds as a console project using Microsoft Visual C++ Express Edition and requires the header file stdafx.h contains the header files:
#include <iomanip>
#include <iostream>
#include <fstream>
Development history:
Initially developed by Tom Young in July and August 2010.
Subsequently developed by Chris Gribble.
*/
#include "stdafx.h"
using namespace System;
using namespace std;
const int maxDirections = 6; /* Maximum number of directions in which path progression can take place from a node. */
const int maxLengths = 343; /* Maximum number of distinct CNSAP lengths allowed. */
const int maxNodes = 343; /* Maximum number of nodes allowed in the bounded lattice. */
const int maxNeighborsPlus3 = 9; /* Maximum number of neighbors a node can have (6) plus 3 */
const int maxShapes = 5000000; /* Maximum number of distinct CNSAP shapes allowed. */
long long i_ll; /* Loop counter. */
long long numberOfPathsPerLength[maxLengths]; /* Number of paths of each length. */
long long numberOfShapesPerLength[maxLengths]; /* Number of distinct path shapes of each length. */
long long endNodePerLength[maxNodes][maxLengths]; /* Number of paths of each length for each ending node. */
long long pathNodePerLength[maxNodes][maxLengths]; /* Number of paths of each length for each path node. */
long long startNodePerLength[maxNodes][maxLengths]; /* Number of paths of each length for each starting node. */
long long endNode[maxNodes]; /* Number of paths for each ending node. */
long long pathNode[maxNodes]; /* Number of paths for each path node. */
long long startNode[maxNodes]; /* Number of paths for each starting node. */
long long startEndNode[maxNodes][maxNodes]; /* Number of paths for each starting-ending node pair. */
long long totalNumberOfPaths; /* Total number of paths. */
long long totalNumberOfShapes; /* Total number of distinct path shapes. */
int currentPath[maxNodes]; /* Sequence of nodes in the current path under construction. */
int nodeNeighbors[maxNodes][maxNeighborsPlus3]; /* Create the node neighbor array: */
/* Column 0 is unused and is an artifact from the translation from Liberty Basic to C++. */
/* Column 1 holds the number of neighbors. */
/* Columns 2 to 7 hold the neighbor node values. */
/* Column 8 holds the value -1. */
/*
int numberOfPathsPerShape[maxShapes]; /* Number of paths with each distinct shape.
*/
int unusableNodes[maxNodes][maxNeighborsPlus3]; /* As a path is created, the starting node and unused neighbors of path nodes are recorded */
/* as unavailable for future use within it. */
int unusedNodes[maxNodes][maxNeighborsPlus3]; /* Records the unused neighbors of each node taken over all CNSAPs constructed. */
/* When a path cannot be made any longer we backtrack and make use of the first */
/* available unused node neighbor to construct a new path. */
int a, b, c; /* Dimensions of lattice boundary in x , y and z directions, respectively. */
int i, j, k, m, n; /* Loop counters. */
int candidateNextNode; /* Candidate for the next node in the path. */
int currentNode; /* The current node at the end of the path under construction. */
int currentNodePointer; /* Points to the current node in the path under construction. */
int firstNode; /* User-specified first node in all CNSAPs. */
int latticeDimension; /* User-specified lattice dimension (2 or 3). */
int longestCNSAP; /* Length of current longest CNSAP for path display control. */
int matchCount; /* Count of those neighbors of firstNode that do not match secondNode. */
int minPathLength, maxPathLength, pathLength; /* Minimum, maximum and current CNSAP lengths. */
int nextNeighborPointer; /* Points to the next node neighbor. */
int nextUnusableNodePointer; /* Points to the next unusable node slot. */
int numberOfNodes; /* Number of nodes in the bounded lattice. */
int numberOfSecondNodes; /* User-specified number of second nodes. */
int secondNode; /* User-specified second node. */
bool addNode; /* Indicates whether candidateNextNode can be added to the path under construction or not. */
bool anyUnusedNodes; /* Indicates whether there are any unused nodes left for path building or not. */
bool finished; /* Indicates whether the program run is finished or not. */
bool noNextNode; /* Indicates whether a path can be extended or not. If not, it is a CNSAP. */
bool shapeMatch; /* Indicates whether the shape of the current CNSAP has already been recorded or not. */
bool unusable; /* Indicates whether a node is recorded as unusable or not. */
char currentPathDirections[maxNodes]; /* Sequence of direction indicators corresponding to the current path. */
char distinctPathShapes[maxShapes][maxNodes]; /* Set of distinct CNSAP shapes generated. */
char nodeNeighborDirections[maxNodes][maxDirections]; /* Indicates direction of each neighbor from each node: */
/* r = right (+x), l = left (-x), u = up (+y), d = down (-y), a = above (+z), b = below (-z)*/
char rotatedPathDirections[maxNodes]; /* Equivalent of currentPathDirections, suitably rotated. */
char allStartNodes; /* User requirement to generate paths starting with each node or one particular node (Y or N). */
char outputAllPaths; /* User requirement to output all paths (Y or N). */
char outputShapeStats; /* User requirement to output path shape statistics. */
char specifySecondNodes; /* User requirement to specify one or more second nodes (Y or N). */
int main ()
{
/*
This program determines the set of all complete non-adjacent paths (CNSAPs) in a square lattice bounded by a rectangle or a cubic lattice
bounded by a rectangular cuboid.
In particular, it determines their lengths and shapes independent of rotation.
In the 2D mode, the user is prompted to supply the dimensions of the rectangle, a and b.
In the 3D mode, the user is prompted to supply the dimensions of the rectangular cuboid, a, b and c.
The user can either choose to generate all paths from all nodes in the lattice or all paths from a user-specified pair of starting nodes.
The first part of the program determines the set of neighbors for each node in the relevant lattice.
The node numbering convention for a selection of 2D lattices is:
a = b = 2 0 1
2 3
a = 2, b = 3 0 1
2 3
4 5
a = 3, b = 2 0 1 2
3 4 5
a = b = 3 0 1 2
3 4 5
6 7 8
a = b = 4 0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
a = b = 5 0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
Direction naming convention:
In a = b = 2, Node 0 is Left of node 1 and Up from Node 2
Node 3 is Right of Node 2 and Down from Node 1
The node numbering convention for a selection of 3D lattices is:
a = b = c = 2 0 1
2 3
4 5
6 7
a = b = c = 3 0 1 2
3 4 5
6 7 8
9 10 11
12 13 14
15 16 17
18 19 20
21 22 23
24 25 26
a = b = c = 4 0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
16 17 18 19
20 21 22 23
24 25 26 27
28 29 30 31
32 33 34 35
36 37 38 39
40 41 42 43
44 45 46 47
48 49 50 51
52 53 54 55
56 57 58 59
60 61 62 63
Direction naming convention:
In a = b = c = 2, Node 0 is Left of node 1, Up from Node 2 and Above Node 4
Node 7 is Right of Node 6 and Down from Node 5 and Below Node 3
*/
/* Create output file. */
fstream file;
file.open("CNSAP.txt", ios_base::out | ios_base::trunc);
/* Initialise variables. */
longestCNSAP = 0; /* Set the longest path encountered so far to zero. */
totalNumberOfShapes = 0; /* Set the number of distinct path shapes encountered to zero. */
for (i = 0; i < maxNodes; i++)
numberOfShapesPerLength[i] = 0;
/* Get lattice type. */
cout << "Enter dimension of lattice [2 = 2D / 3 = 3D] ";
cin >> latticeDimension;
if (latticeDimension != 2 && latticeDimension != 3)
goto error;
if (latticeDimension == 2)
{
/* Get dimensions of lattice. */
cout << "Enter length of rectangle > 1, a = "; /* Get the length dimension a a a a */
cin >> a;
if (a < 2)
goto error;
cout << "Enter width of rectangle > 1, b = "; /* Get the width dimension b */
cin >> b; /* b */
/* b */
/* b */
if (b < 2)
goto error;
numberOfNodes = a * b;
if (numberOfNodes > maxNodes)
goto error;
file << "Lattice has 2 dimensions" << endl;
file << "Length of rectangle, a = " << a << endl;
file << "Width of rectangle, b = " << b << endl;
/* Initialise minimum and maximum path lengths. */
minPathLength = numberOfNodes;
maxPathLength = 0;
/* The first part of the program creates the neighbor array. This part of the program has 3 parts. */
/* Make sure the array is clean. */
for (i = 0; i < numberOfNodes; i++)
{
for (k = 1; k < maxNeighborsPlus3; k++)
{
nodeNeighbors[i][k] = 0;
}
for (k = 0; k < maxDirections; k++)
{
nodeNeighborDirections[i][k] = ' ';
}
}
/* Part one identifies the corner points of the lattice, each of which has 2 neighbors, */
/* and identifies them. */
/* Part One */
/* Top left hand corner. */
n = 0;
nodeNeighbors[n][1] = 2;
nodeNeighbors[n][2] = 1;
nodeNeighbors[n][3] = a;
nodeNeighborDirections[n][0] = 'r'; /* Node 1 is one step right from node 0. */
nodeNeighborDirections[n][1] = 'd'; /* Node a is one step down from node 0. */
/* Top right hand corner. */
n = a - 1;
nodeNeighbors[n][1] = 2;
nodeNeighbors[n][2] = a - 2;
nodeNeighbors[n][3] = 2 * a - 1;
nodeNeighborDirections[n][0] = 'l'; /* Node (a - 2) is one step left from node (a - 1). */
nodeNeighborDirections[n][1] = 'd'; /* Node (2a - 1) is one step down from node (a - 1). */
/* Bottom left hand corner. */
n = a * b - a;
nodeNeighbors[n][1] = 2;
nodeNeighbors[n][2] = a * b - 2 * a;
nodeNeighbors[n][3] = a * b - a + 1;
nodeNeighborDirections[n][0] = 'u'; /* Node (ab - 2a) is one step up from node (ab - a). */
nodeNeighborDirections[n][1] = 'r'; /* Node (ab - a + 1) is one step right from node (ab - a). */
/* Bottom right hand corner. */
n = a * b - 1;
nodeNeighbors[n][1] = 2;
nodeNeighbors[n][2] = a * b - a - 1;
nodeNeighbors[n][3] = a * b - 2;
nodeNeighborDirections[n][0] = 'u'; /* Node (ab - a - 1) is one step up from node (ab - 1). */
nodeNeighborDirections[n][1] = 'l'; /* Node (ab - 2) is one step left from node (ab - 1). */
/* Part Two figures out the lattice points that have 3 neighbors. */
/* These points reside along the 4 edges of the rectangle and are not corner points. */
/* Part Two */
/* Edges in the length [a] direction. This will not be done if a = 2 since there are no edge nodes then. */
if (a > 2)
{
/* Top edge. */
for (i = 1; i <= a - 2; i++)
{
nodeNeighbors[i][1] = 3;
nodeNeighbors[i][2] = i - 1;
nodeNeighbors[i][3] = i + 1;
nodeNeighbors[i][4] = i + a;
nodeNeighborDirections[i][0] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][1] = 'r'; /* Node i + 1 is one step right from node i. */
nodeNeighborDirections[i][2] = 'd'; /* Node i + a is one step down from node i. */
}
/* Bottom edge. */
for (i = a * b - a + 1; i <= a * b - 2; i++)
{
nodeNeighbors[i][1] = 3;
nodeNeighbors[i][2] = i - a;
nodeNeighbors[i][3] = i - 1;
nodeNeighbors[i][4] = i + 1;
nodeNeighborDirections[i][0] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][1] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][2] = 'r'; /* Node i + 1 is one step right from node i. */
}
}
/* Edges in the length [b] direction. */
if (b > 2)
{
/* Left hand edge. */
for (i = a; i <= a * b - 2 * a; i += a)
{
nodeNeighbors[i][1] = 3;
nodeNeighbors[i][2] = i - a;
nodeNeighbors[i][3] = i + 1;
nodeNeighbors[i][4] = i + a;
nodeNeighborDirections[i][0] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][1] = 'r'; /* Node i + 1 is one step right from node i. */
nodeNeighborDirections[i][2] = 'd'; /* Node i + a is one step down from node i. */
}
/* Right hand edge. */
for (i = 2 * a - 1; i <= a * b - a - 1; i += a)
{
nodeNeighbors[i][1] = 3;
nodeNeighbors[i][2] = i - a;
nodeNeighbors[i][3] = i - 1;
nodeNeighbors[i][4] = i + a;
nodeNeighborDirections[i][0] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][1] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][2] = 'd'; /* Node i + a is one step down from node i. */
}
}
/* Part Three identifies the lattice points that have 4 neighbors. */
/* These points all lie within the rectangle. */
/* Part Three */
for (i = 0; i < numberOfNodes; i++)
{
if (nodeNeighbors[i][1] == 0)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a;
nodeNeighbors[i][3] = i - 1;
nodeNeighbors[i][4] = i + 1;
nodeNeighbors[i][5] = i + a;
nodeNeighborDirections[i][0] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][1] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][2] = 'r'; /* Node i + 1 is one step right from node i. */
nodeNeighborDirections[i][3] = 'd'; /* Node i + a is one step down from node i. */
}
}
}
else if (latticeDimension == 3)
{
/* Get dimensions of lattice. */
cout << "Enter length of cuboid, a = "; /* Get the length dimension a a a a */
cin >> a;
if (a < 2)
goto error;
cout << "Enter width of cuboid, b = "; /* Get the width dimension b */
cin >> b; /* b */
/* b */
/* b */
if (b < 2)
goto error;
cout << "Enter height of cuboid, c = "; /* Get the height dimension c */
cin >> c; /* c */
/* c */
/* c */
if (c < 2)
goto error;
numberOfNodes = a * b * c;
if (numberOfNodes > maxNodes)
goto error;
file << "Lattice has 3 dimensions" << endl;
file << "Length of cuboid, a = " << a << endl;
file << "Width of cuboid, b = " << b << endl;
file << "Height of cuboid, c = " << c << endl;
/* Initialise minimum and maximum path lengths. */
minPathLength = numberOfNodes;
maxPathLength = 0;
/* The first part of the program creates the neighbor array. This part of the program has 4 parts. */
/* Make sure the array is clean. */
for (i = 0; i < numberOfNodes; i++)
{
for (k = 1; k < maxNeighborsPlus3; k++)
{
nodeNeighbors[i][k] = 0;
}
}
/* Part one finds the corner points of the lattice and assigns them the number 3 since they have three neighbors. */
/* Then, for each corner, it figures out the neighbors. */
/* Part One */
/* Upper face, top left hand corner. */
n = 0;
nodeNeighbors[n][1] = 3;
nodeNeighbors[n][2] = n + 1;
nodeNeighbors[n][3] = n + a;
nodeNeighbors[n][4] = n + a * b;
nodeNeighborDirections[n][0] = 'r'; /* Node n + 1 is one step right from node n. */
nodeNeighborDirections[n][1] = 'd'; /* Node n + a is one step down from node n. */
nodeNeighborDirections[n][2] = 'b'; /* Node n + ab is one step below node n. */
/* Upper face, top right hand corner. */
n = a - 1;
nodeNeighbors[n][1] = 3;
nodeNeighbors[n][2] = n - 1;
nodeNeighbors[n][3] = n + a;
nodeNeighbors[n][4] = n + a * b;
nodeNeighborDirections[n][0] = 'l'; /* Node n - 1 is one step left from node n. */
nodeNeighborDirections[n][1] = 'd'; /* Node n - a is one step down from node n. */
nodeNeighborDirections[n][2] = 'b'; /* Node n + ab is one step below node n. */
/* Upper face, bottom left hand corner. */
n = a * b - a;
nodeNeighbors[n][1] = 3;
nodeNeighbors[n][2] = n - a;
nodeNeighbors[n][3] = n + 1;
nodeNeighbors[n][4] = n + a * b;
nodeNeighborDirections[n][0] = 'u'; /* Node n - a is one step up from node n. */
nodeNeighborDirections[n][1] = 'r'; /* Node n + 1 is one step right from node n. */
nodeNeighborDirections[n][2] = 'b'; /* Node n + ab is one step below node n. */
/* Upper face, bottom right hand corner. */
n = a * b - 1;
nodeNeighbors[n][1] = 3;
nodeNeighbors[n][2] = n - a;
nodeNeighbors[n][3] = n - 1;
nodeNeighbors[n][4] = n + a * b;
nodeNeighborDirections[n][0] = 'u'; /* Node n - a is one step up from node n. */
nodeNeighborDirections[n][1] = 'l'; /* Node n - 1 is one step left from node n. */
nodeNeighborDirections[n][2] = 'b'; /* Node n + ab is one step below node n. */
/* Lower face, top left hand corner. */
n = a * b * c - a * b;
nodeNeighbors[n][1] = 3;
nodeNeighbors[n][2] = n - a * b;
nodeNeighbors[n][3] = n + 1;
nodeNeighbors[n][4] = n + a;
nodeNeighborDirections[n][0] = 'a'; /* Node n - ab is one step above node n. */
nodeNeighborDirections[n][1] = 'r'; /* Node n + 1 is one step right from node n. */
nodeNeighborDirections[n][2] = 'd'; /* Node n + a is one step down from node n. */
/* Lower face, top right hand corner. */
n = a * b * c - a * b + a - 1;
nodeNeighbors[n][1] = 3;
nodeNeighbors[n][2] = n - a * b;
nodeNeighbors[n][3] = n - 1;
nodeNeighbors[n][4] = n + a;
nodeNeighborDirections[n][0] = 'a'; /* Node n - ab is one step above node n. */
nodeNeighborDirections[n][1] = 'l'; /* Node n - 1 is one step left from node n. */
nodeNeighborDirections[n][2] = 'd'; /* Node n + a is one step down from node n. */
/* Lower face, bottom left hand corner. */
n = a * b * c - a;
nodeNeighbors[n][1] = 3;
nodeNeighbors[n][2] = n - a * b;
nodeNeighbors[n][3] = n - a;
nodeNeighbors[n][4] = n + 1;
nodeNeighborDirections[n][0] = 'a'; /* Node n - ab is one step above node n. */
nodeNeighborDirections[n][1] = 'u'; /* Node n - a is one step up from node n. */
nodeNeighborDirections[n][2] = 'r'; /* Node n + 1 is one step right from node n. */
/* Lower face, bottom right hand corner. */
n = a * b * c - 1;
nodeNeighbors[n][1] = 3;
nodeNeighbors[n][2] = n - a * b;
nodeNeighbors[n][3] = n - a;
nodeNeighbors[n][4] = n - 1;
nodeNeighborDirections[n][0] = 'a'; /* Node n - ab is one step above node n. */
nodeNeighborDirections[n][1] = 'u'; /* Node n - a is one step up from node n. */
nodeNeighborDirections[n][2] = 'l'; /* Node n - 1 is one step left from node n. */
/* Part Two figures out the lattice points that have 4 neighbors. */
/* These points reside along the edges of the cube. */
/* Since there are twelve edges, we need twelve loops. */
/*Part Two*/
/*Top and bottom face edges in the length [a] direction. This will not be done if a = 2 since there are no edge nodes then. */
if (a > 2)
{
for (i = 1; i <= a - 2; i++)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - 1;
nodeNeighbors[i][3] = i + 1;
nodeNeighbors[i][4] = i + a;
nodeNeighbors[i][5] = i + a * b;
nodeNeighborDirections[i][0] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][1] = 'r'; /* Node i + 1 is one step right from node i. */
nodeNeighborDirections[i][2] = 'd'; /* Node i + a is one step down from node i. */
nodeNeighborDirections[i][3] = 'b'; /* Node i + ab is one step below node i. */
}
for (i = a * b - a + 1; i <= a * b - 2; i++)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a;
nodeNeighbors[i][3] = i - 1;
nodeNeighbors[i][4] = i + 1;
nodeNeighbors[i][5] = i + a * b;
nodeNeighborDirections[i][0] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][1] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][2] = 'r'; /* Node i + 1 is one step right from node i. */
nodeNeighborDirections[i][3] = 'b'; /* Node i + ab is one step below node i. */
}
for (i = a * b * c - a * b + 1; i <= a * b * c - a * b + a - 2; i++)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a * b;
nodeNeighbors[i][3] = i - 1;
nodeNeighbors[i][4] = i + 1;
nodeNeighbors[i][5] = i + a;
nodeNeighborDirections[i][0] = 'a'; /* Node i - ab is one step above node i. */
nodeNeighborDirections[i][1] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][2] = 'r'; /* Node i + 1 is one step right from node i. */
nodeNeighborDirections[i][3] = 'd'; /* Node i + a is one step down from node i. */
}
for (i = a * b * c - a + 1; i <= a * b * c - 2; i++)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a * b;
nodeNeighbors[i][3] = i - a;
nodeNeighbors[i][4] = i - 1;
nodeNeighbors[i][5] = i + 1;
nodeNeighborDirections[i][0] = 'a'; /* Node i - ab is one step above node i. */
nodeNeighborDirections[i][1] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][2] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][3] = 'r'; /* Node i + 1 is one step right from node i. */
}
}
/* Top and bottom face edges in the length [b] direction. */
if (b > 2)
{
for (i = a; i <= a * b - 2 * a; i += a)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a;
nodeNeighbors[i][3] = i + 1;
nodeNeighbors[i][4] = i + a;
nodeNeighbors[i][5] = i + a * b;
nodeNeighborDirections[i][0] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][1] = 'r'; /* Node i + 1 is one step right from node i. */
nodeNeighborDirections[i][2] = 'd'; /* Node i + a is one step down from node i. */
nodeNeighborDirections[i][3] = 'b'; /* Node i + ab is one step below node i. */
}
for (i = 2 * a - 1; i <= a * b - a - 1; i += a)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a;
nodeNeighbors[i][3] = i - 1;
nodeNeighbors[i][4] = i + a;
nodeNeighbors[i][5] = i + a * b;
nodeNeighborDirections[i][0] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][1] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][2] = 'd'; /* Node i + a is one step down from node i. */
nodeNeighborDirections[i][3] = 'b'; /* Node i + ab is one step below node i. */
}
for (i = a * b * c - a * b + a; i <= a * b * c - 2 * a; i += a)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a * b;
nodeNeighbors[i][3] = i - a;
nodeNeighbors[i][4] = i + 1;
nodeNeighbors[i][5] = i + a;
nodeNeighborDirections[i][0] = 'a'; /* Node i - ab is one step above node i. */
nodeNeighborDirections[i][1] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][2] = 'r'; /* Node i + 1 is one step right from node i. */
nodeNeighborDirections[i][3] = 'd'; /* Node i + a is one step down from node i. */
}
for (i = a * b * c - a * b + 2 * a - 1; i <= a * b * c - a - 1; i += a)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a * b;
nodeNeighbors[i][3] = i - a;
nodeNeighbors[i][4] = i - 1;
nodeNeighbors[i][5] = i + a;
nodeNeighborDirections[i][0] = 'a'; /* Node i - ab is one step above node i. */
nodeNeighborDirections[i][1] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][2] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][3] = 'd'; /* Node i + a is one step down from node i. */
}
}
/* Lateral edges. */
if (c > 2)
{
for (i = a * b; i <= a * b * c - 2 * a * b; i += a * b)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a * b;
nodeNeighbors[i][3] = i + 1;
nodeNeighbors[i][4] = i + a;
nodeNeighbors[i][5] = i + a * b;
nodeNeighborDirections[i][0] = 'a'; /* Node i - ab is one step above node i. */
nodeNeighborDirections[i][1] = 'r'; /* Node i + 1 is one step right from node i. */
nodeNeighborDirections[i][2] = 'd'; /* Node i + a is one step down from node i. */
nodeNeighborDirections[i][3] = 'b'; /* Node i + ab is one step below node i. */
}
for (i = a * b + a - 1; i <= a * b * c - 2 * a * b + a - 1; i += a * b)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a * b;
nodeNeighbors[i][3] = i - 1;
nodeNeighbors[i][4] = i + a;
nodeNeighbors[i][5] = i + a * b;
nodeNeighborDirections[i][0] = 'a'; /* Node i - ab is one step above node i. */
nodeNeighborDirections[i][1] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][2] = 'd'; /* Node i + a is one step down from node i. */
nodeNeighborDirections[i][3] = 'b'; /* Node i + ab is one step below node i. */
}
for (i = 2 * a * b - a; i <= a * b * c - a * b - a; i += a * b)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a * b;
nodeNeighbors[i][3] = i - a;
nodeNeighbors[i][4] = i + 1;
nodeNeighbors[i][5] = i + a * b;
nodeNeighborDirections[i][0] = 'a'; /* Node i - ab is one step above node i. */
nodeNeighborDirections[i][1] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][2] = 'r'; /* Node i + 1 is one step right from node i. */
nodeNeighborDirections[i][3] = 'b'; /* Node i + ab is one step below node i. */
}
for (i = 2 * a * b - 1; i <= a * b * c - a * b - 1; i += a * b)
{
nodeNeighbors[i][1] = 4;
nodeNeighbors[i][2] = i - a * b;
nodeNeighbors[i][3] = i - a;
nodeNeighbors[i][4] = i - 1;
nodeNeighbors[i][5] = i + a * b;
nodeNeighborDirections[i][0] = 'a'; /* Node i - ab is one step above node i. */
nodeNeighborDirections[i][1] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][2] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][3] = 'b'; /* Node i + ab is one step below node i. */
}
}
/* Part Three */
/* Each lattice point that is on the inside of a face has 5 neighbors. */
if (a > 2 && b > 2)
{
/* Top face. */
for (i = 1; i <= b - 2; i++)
{
for (k = 1; k <= a - 2; k++)
{
n = i * a + k;
nodeNeighbors[n][1] = 5;
nodeNeighbors[n][2] = n - a;
nodeNeighbors[n][3] = n - 1;
nodeNeighbors[n][4] = n + 1;
nodeNeighbors[n][5] = n + a;
nodeNeighbors[n][6] = n + a * b;
nodeNeighborDirections[n][0] = 'u'; /* Node n - a is one step up from node n. */
nodeNeighborDirections[n][1] = 'l'; /* Node n - 1 is one step left from node n. */
nodeNeighborDirections[n][2] = 'r'; /* Node n + 1 is one step right from node n. */
nodeNeighborDirections[n][3] = 'd'; /* Node n + a is one step down from node n. */
nodeNeighborDirections[n][4] = 'b'; /* Node n + ab is one step below node n. */
}
}
/* Bottom face. */
for (i = 1; i <= b - 2; i++)
{
for (k = 1; k <= a - 2; k++)
{
n = i * a + k + a * b * (c - 1);
nodeNeighbors[n][1] = 5;
nodeNeighbors[n][2] = n - a * b;
nodeNeighbors[n][3] = n - a;
nodeNeighbors[n][4] = n - 1;
nodeNeighbors[n][5] = n + 1;
nodeNeighbors[n][6] = n + a;
nodeNeighborDirections[n][0] = 'a'; /* Node n - ab is one step above node n. */
nodeNeighborDirections[n][1] = 'u'; /* Node n - a is one step up from node n. */
nodeNeighborDirections[n][2] = 'l'; /* Node n - 1 is one step left from node n. */
nodeNeighborDirections[n][3] = 'r'; /* Node n + 1 is one step right from node n. */
nodeNeighborDirections[n][4] = 'd'; /* Node n + a is one step down node n. */
}
}
}
if (a > 2 && c > 2)
{
/* Front face. */
for (i = 1; i <= c - 2; i++)
{
for (k = 1; k <= a - 2; k++)
{
n = (i + 1) * a * b + k - a;
nodeNeighbors[n][1] = 5;
nodeNeighbors[n][2] = n - a * b;
nodeNeighbors[n][3] = n - a;
nodeNeighbors[n][4] = n - 1;
nodeNeighbors[n][5] = n + 1;
nodeNeighbors[n][6] = n + a * b;
nodeNeighborDirections[n][0] = 'a'; /* Node n - ab is one step above node n. */
nodeNeighborDirections[n][1] = 'u'; /* Node n - a is one step up from node n. */
nodeNeighborDirections[n][2] = 'l'; /* Node n - 1 is one step left from node n. */
nodeNeighborDirections[n][3] = 'r'; /* Node n + 1 is one step right from node n. */
nodeNeighborDirections[n][4] = 'b'; /* Node n + ab is one step below node n. */
}
}
/* Back face. */
for (i = 1; i <= c - 2; i++)
{
for (k = 1; k <= a - 2; k++)
{
n = i * a * b + k;
nodeNeighbors[n][1] = 5;
nodeNeighbors[n][2] = n - a * b;
nodeNeighbors[n][3] = n - 1;
nodeNeighbors[n][4] = n + 1;
nodeNeighbors[n][5] = n + a;
nodeNeighbors[n][6] = n + a * b;
nodeNeighborDirections[n][0] = 'a'; /* Node n - ab is one step above node n. */
nodeNeighborDirections[n][1] = 'l'; /* Node n - 1 is one step left from node n. */
nodeNeighborDirections[n][2] = 'r'; /* Node n + 1 is one step right from node n. */
nodeNeighborDirections[n][3] = 'd'; /* Node n + a is one step down from node n. */
nodeNeighborDirections[n][4] = 'b'; /* Node n + ab is one step below node n. */
}
}
}
if (b > 2 && c > 2)
{
/* Right face. */
for (i = 1; i <= c - 2; i++)
{
for (k = 1; k <= b - 2; k++)
{
n = i * a * b + a * k + a - 1;
nodeNeighbors[n][1] = 5;
nodeNeighbors[n][2] = n - a * b;
nodeNeighbors[n][3] = n - a;
nodeNeighbors[n][4] = n - 1;
nodeNeighbors[n][5] = n + a;
nodeNeighbors[n][6] = n + a * b;
nodeNeighborDirections[n][0] = 'a'; /* Node n - ab is one step above node n. */
nodeNeighborDirections[n][1] = 'u'; /* Node n - a is one step up from node n. */
nodeNeighborDirections[n][2] = 'l'; /* Node n - 1 is one step left from node n. */
nodeNeighborDirections[n][3] = 'd'; /* Node n + a is one step down from node n. */
nodeNeighborDirections[n][4] = 'b'; /* Node n + ab is one step below node n. */
}
}
/* Left face. */
for (i = 1; i <= c - 2; i++)
{
for (k = 1; k <= b - 2; k++)
{
n = i * a * b + k * a;
nodeNeighbors[n][1] = 5;
nodeNeighbors[n][2] = n - a * b;
nodeNeighbors[n][3] = n - a;
nodeNeighbors[n][4] = n + 1;
nodeNeighbors[n][5] = n + a;
nodeNeighbors[n][6] = n + a * b;
nodeNeighborDirections[n][0] = 'a'; /* Node n - ab is one step above node n. */
nodeNeighborDirections[n][1] = 'u'; /* Node n - a is one step up from node n. */
nodeNeighborDirections[n][2] = 'r'; /* Node n + 1 is one step right from node n. */
nodeNeighborDirections[n][3] = 'd'; /* Node n + a is one step down from node n. */
nodeNeighborDirections[n][4] = 'b'; /* Node n + ab is one step below node n. */
}
}
}
/* Part Four */
/* Every other node must be inside the cuboid and has 6 neighbors. */
for (i = 0; i < numberOfNodes; i++)
{
if (nodeNeighbors[i][1] == 0)
{
nodeNeighbors[i][1] = 6;
nodeNeighbors[i][2] = i - a * b;
nodeNeighbors[i][3] = i - a;
nodeNeighbors[i][4] = i - 1;
nodeNeighbors[i][5] = i + 1;
nodeNeighbors[i][6] = i + a;
nodeNeighbors[i][7] = i + a * b;
nodeNeighborDirections[i][0] = 'a'; /* Node i - ab is one step above node i. */
nodeNeighborDirections[i][1] = 'u'; /* Node i - a is one step up from node i. */
nodeNeighborDirections[i][2] = 'l'; /* Node i - 1 is one step left from node i. */
nodeNeighborDirections[i][3] = 'r'; /* Node i + 1 is one step right from node i. */
nodeNeighborDirections[i][4] = 'd'; /* Node i + a is one step down from node i. */
nodeNeighborDirections[i][5] = 'b'; /* Node i + ab is one step below node i. */
}
}
}
/* Change all zeroes at end of nodeNeighbors to -1...the rest of the program needs this??????? */
for (i = 0; i < numberOfNodes; i++)
{
for (j = nodeNeighbors[i][1] + 2; j < maxNeighborsPlus3; j++)
{
nodeNeighbors[i][j]= -1;
}
}
/* Get output requirements. */
cout << "Output all paths? [y / n] ";
cin >> outputAllPaths;
file << "Output all paths = " << outputAllPaths << endl;
if (outputAllPaths != 'y' && outputAllPaths != 'n')
goto error;
cout << "Output shape stats? [y / n] ";
cin >> outputShapeStats;
file << "Output shape stats = " << outputShapeStats << endl;
if (outputShapeStats != 'y' && outputShapeStats != 'n')
goto error;
/* Get starting node requirements. */
cout << "Run with all starting nodes? [y / n] ";
cin >> allStartNodes;
file << "Run with all starting nodes = " << allStartNodes << endl;
if (allStartNodes != 'y' && allStartNodes != 'n')
goto error;
if (allStartNodes == 'n')
{
/* Generate all CNSAPs starting with a user-specified first node and optionally, one or more second nodes. */
/* Initialise arrays holding node values to the invalid node number -1. */
for (i = 0; i < numberOfNodes; i++)
{
currentPath[i] = -1;
for (k = 1; k < maxNeighborsPlus3; k++)
{
unusableNodes[i][k] = -1;
unusedNodes[i][k] = -1;
}
}
/* Prompt user to enter the first node. */
cout << "Type in the first node number ";
cin >> firstNode;
file << "First node = " << firstNode << endl;
if (firstNode < 0 || firstNode > numberOfNodes - 1)
goto error;
currentNodePointer = 0;
currentPath[currentNodePointer] = firstNode; /* Puts the first node in the path. */
unusableNodes[currentNodePointer][1] = firstNode; /* Ensures that the first node cannot be used again in this path. */
/* Are one or more second nodes required? */
cout << "Do you want to enter one or more second nodes? [y / n] ";
cin >> specifySecondNodes;
file << "Second node requirement = " << specifySecondNodes << endl;
if (specifySecondNodes == 'y')
{
currentNodePointer++;
cout << "How many second nodes? ";
cin >> numberOfSecondNodes;
file << "Number of second nodes = " << numberOfSecondNodes << endl;
if (numberOfSecondNodes < 0 || numberOfSecondNodes > nodeNeighbors[firstNode][1])
goto error;
for (i = 1; i <= numberOfSecondNodes; i++)
{
cout << "Type in a second node number ";
cin >> secondNode;
file << "Second node = " << secondNode << endl;
matchCount = 0;
for (j = 1; j <= nodeNeighbors[firstNode][1]; j++)
{
if (secondNode != nodeNeighbors[firstNode][j + 1])
matchCount++;
}
if (matchCount == nodeNeighbors[firstNode][1])
goto error; /* Second node entered is not a neighbor of the first. */
if (i == 1)
{
/* Place the initial second node in the path and register all neighbors of the first node as unusable. */
currentPath[currentNodePointer] = secondNode;
for (j = 1; j <= nodeNeighbors[firstNode][1]; j++)
{
unusableNodes[currentNodePointer][j] = nodeNeighbors[firstNode][j + 1];
}
}
else
{
/* Check that this alternative second node has not already been specified. */
if (secondNode == currentPath[currentNodePointer])
goto error;
for (j = 1; j < i; j++)
{
if (secondNode == unusedNodes[currentNodePointer][j])
goto error;
}
/* As it has not already been specified, store it as an unused node for future use. */
unusedNodes[currentNodePointer][i - 1] = secondNode;
}
}
}
cout << endl;
file << endl;
/* Compute all the CNSAPs starting with the first and each of the second nodes specified. */
finished = false;
while (finished == false)
{
noNextNode = false;
while (noNextNode == false)
{
/* Point to the first neighbor. */
nextNeighborPointer = 2;
currentNode = currentPath[currentNodePointer];
do
{
candidateNextNode = nodeNeighbors[currentNode][nextNeighborPointer];
/* Now check to see if we can include this node in the path. */
addNode = true;
for (j = 0; j <= currentNodePointer; j++)
{
for (k = 1; k < maxNeighborsPlus3; k++)
{
if (candidateNextNode == unusableNodes[j][k])
{
addNode = false;
break;
}
}
if (addNode == false)
break;
}
nextNeighborPointer++;
}
while (addNode == false && candidateNextNode != -1);
/* To reach this point in the progam, we have either found a next node in the path or the path is complete. */
if (candidateNextNode == -1)
noNextNode = true;
if ((noNextNode == false) && (addNode == true))
{
currentNodePointer++;
currentPath[currentNodePointer] = candidateNextNode;
/* Since we've added the node to the path, make its usable neighbors unusable. */
nextUnusableNodePointer = 1;
for (i = 1; i <= nodeNeighbors[currentPath[currentNodePointer - 1]][1]; i++)
{
unusable = false;
for (j = 0; j < currentNodePointer; j++)
{
for (k = 1; k < maxNeighborsPlus3; k++)
{
if (unusableNodes[j][k] == -1)
break;
if (nodeNeighbors[currentPath[currentNodePointer - 1]][i + 1] == unusableNodes[j][k])
unusable = true;
}
}
if (unusable == false)
{
/* This node neighbor is not already unusable, so make it so. */
unusableNodes[currentNodePointer][nextUnusableNodePointer] = nodeNeighbors[currentPath[currentNodePointer - 1]][i + 1];
nextUnusableNodePointer++;
}
}
/* Record any unused unusable nodes in the current path as available for use in future paths. */
for (i = 2; i < maxNeighborsPlus3; i++)
{
unusedNodes[currentNodePointer][i - 1] = unusableNodes[currentNodePointer][i];
}
}
}
/* The path is complete because we didn't find a candidate for the next node. */
if (outputAllPaths == 'n')
{
if (currentNodePointer + 1 >= longestCNSAP)
{
cout << "Path = ";
file << "Path = ";
for (i = 0; i <= currentNodePointer; i++)
{
cout << " " << currentPath[i];
file << " " << currentPath[i];
}
cout << "; Length = " << currentNodePointer + 1 << endl;
file << "; Length = " << currentNodePointer + 1 << endl;
longestCNSAP = currentNodePointer + 1;
}
}
else
{
cout << "Path =";
file << "Path =";
for (i = 0; i <= currentNodePointer; i++)
{
cout << " " << currentPath[i];
file << " " << currentPath[i];
}
cout << "; Length = " << currentNodePointer + 1 << endl;
file << "; Length = " << currentNodePointer + 1 << endl;
}
/* Increment the number of paths of this length. */
pathLength = currentNodePointer + 1;
numberOfPathsPerLength[pathLength] = numberOfPathsPerLength[pathLength] + 1;
/* Determine minimum and maximum path lengths. */
minPathLength = min (minPathLength, pathLength);
maxPathLength = max (maxPathLength, pathLength);
/* Continue CNSAP construction until there are no unused nodes. */
anyUnusedNodes = true;
while (anyUnusedNodes == true)
{
if (unusedNodes[currentNodePointer][1] != -1)
{
anyUnusedNodes = false;
currentPath[currentNodePointer] = unusedNodes[currentNodePointer][1];
for (i = 1; i < maxNeighborsPlus3; i++)
{
unusedNodes[currentNodePointer][i] = unusedNodes[currentNodePointer][i + 1];
currentPath[currentNodePointer + i] = -1;
}
}
else
{
/* There are no more neighbors of the current node that we can branch to, so we have to wipe out these nodes from the unusableNodes array */
/* so that neighbors from the next current node can be inserted. */
for (i = 1; i < maxNeighborsPlus3; i++)
{
unusableNodes[currentNodePointer][i] = -1;
}
/* Backtrack to the previous node. */
currentNodePointer--;
}
if (currentNodePointer == 0)
{
finished = true;
anyUnusedNodes = false;
}
}
}
file << endl << "Column headings:" << endl;
file << " L = Path Length" << endl;
file << " N = Total number of paths with length L" << endl << endl;
file << "L N" << endl;
totalNumberOfPaths = 0;
for (i = minPathLength; i <= maxPathLength; i++)
{
file << i << " " << numberOfPathsPerLength[i] << " " << endl;
totalNumberOfPaths = totalNumberOfPaths + numberOfPathsPerLength[i];
}
file << "Total " << totalNumberOfPaths << " " << endl << endl;
}
else
{
/* Generate all paths starting with each node. */
file << endl;
for (m = 0; m < numberOfNodes; m++)
{
/* Initialise variables. */
for (i = 0; i < numberOfNodes; i++)
{
currentPath[i] = -1;
for (k = 1; k < maxNeighborsPlus3; k++)
{
unusableNodes[i][k] = -1;
unusedNodes[i][k] = -1;
}
}
currentNodePointer = 0;
currentPath[currentNodePointer] = m;
unusableNodes[currentNodePointer][1] = m;
/* The first node is set so compute all CNSAPs emanating from this node. */
finished = false;
while (finished == false)
{
noNextNode = false;
while (noNextNode == false)
{
nextNeighborPointer = 2;
currentNode = currentPath[currentNodePointer];
do
{
candidateNextNode = nodeNeighbors[currentNode][nextNeighborPointer];
/* Now check to see if we can move to this node. */
addNode = true;
for (j = 0; j <= currentNodePointer; j++)
{
for (k = 1; k < maxNeighborsPlus3; k++)
{
if (candidateNextNode == unusableNodes[j][k])
{
addNode = false;
break;
}
}
if (addNode == false)
break;
}
nextNeighborPointer++;
}
while (addNode == false && candidateNextNode != -1);
/* To reach this point in the progam, we have either found a next node in the path or the path is complete. */
if (candidateNextNode == -1)
noNextNode = true;
if ((noNextNode == false) && (addNode == true))
{
currentNodePointer++;
currentPath[currentNodePointer] = candidateNextNode;
currentPathDirections[currentNodePointer] = nodeNeighborDirections[currentNode][nextNeighborPointer - 3];
/* Since we've added a node to the path, make its usable neighbors unusable. */
nextUnusableNodePointer = 1;
for (i = 1; i <= nodeNeighbors[currentPath[currentNodePointer - 1]][1]; i++)
{
unusable = false;
for (j = 0; j < currentNodePointer; j++)
{
for (k = 1; k < maxNeighborsPlus3; k++)
{
if (nodeNeighbors[currentPath[currentNodePointer - 1]][i + 1] == unusableNodes[j][k])
unusable = true;
}
}
if (unusable == false)
{
unusableNodes[currentNodePointer][nextUnusableNodePointer] = nodeNeighbors[currentPath[currentNodePointer - 1]][i + 1];
nextUnusableNodePointer++;
}
}
/* Record any unused unusable nodes in the current path as available for use in future paths. */
for (i = 2; i < maxNeighborsPlus3; i++)
{
unusedNodes[currentNodePointer][i - 1] = unusableNodes[currentNodePointer][i];
}
}
}
/* The path is complete because we didn't find a candidateNextNode. */
if (outputShapeStats == 'n') goto skip_shapes;
/* Compute path shape stats. */
/* Rotate the directional representation of the path so that the starting direction is "up". */
if (latticeDimension == 2)
{
rotatedPathDirections[0] = ' ';
if (currentPathDirections[1] == 'd')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'd';
}
}
else if (currentPathDirections[1] == 'l')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'r';
}
}
else if (currentPathDirections[1] == 'r')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'l';
}
}
else if (currentPathDirections[1] == 'u')
{
for (i = 1; i <= currentNodePointer; i++)
{
rotatedPathDirections[i] = currentPathDirections[i];
}
}
rotatedPathDirections[currentNodePointer + 1] = '\0';
}
else if (latticeDimension == 3)
{
rotatedPathDirections[0] = ' ';
if (currentPathDirections[1] == 'a')
{
j = 2;
while (currentPathDirections[j] == 'a')
{
j++;
}
if (currentPathDirections[j] == 'd')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'l';
}
}
else if (currentPathDirections[j] == 'l')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'a';
}
}
else if (currentPathDirections[j] == 'r')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'b';
}
}
else if (currentPathDirections[j] == 'u')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'r';
}
}
}
else if (currentPathDirections[1] == 'b')
{
j = 2;
while (currentPathDirections[j] == 'b')
{
j++;
}
if (currentPathDirections[j] == 'd')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'l';
}
}
else if (currentPathDirections[j] == 'l')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'b';
}
}
else if (currentPathDirections[j] == 'r')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'a';
}
}
else if (currentPathDirections[j] == 'u')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'r';
}
}
}
else if (currentPathDirections[1] == 'd')
{
j = 2;
while (currentPathDirections[j] == 'd')
{
j++;
}
if (currentPathDirections[j] == 'a')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'd';
}
}
else if (currentPathDirections[j] == 'b')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'd';
}
}
else if (currentPathDirections[j] == 'l')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'd';
}
}
else if (currentPathDirections[j] == 'r')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'd';
}
}
}
else if (currentPathDirections[1] == 'l')
{
j = 2;
while (currentPathDirections[j] == 'l')
{
j++;
}
if (currentPathDirections[j] == 'a')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'b';
}
}
else if (currentPathDirections[j] == 'b')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'a';
}
}
else if (currentPathDirections[j] == 'd')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'l';
}
}
else if (currentPathDirections[j] == 'u')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'r';
}
}
}
else if (currentPathDirections[1] == 'r')
{
j = 2;
while (currentPathDirections[j] == 'r')
{
j++;
}
if (currentPathDirections[j] == 'a')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'a';
}
}
else if (currentPathDirections[j] == 'b')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'b';
}
}
else if (currentPathDirections[j] == 'd')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'l';
}
}
else if (currentPathDirections[j] == 'u')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'u';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'r';
}
}
}
else if (currentPathDirections[1] == 'u')
{
j = 2;
while (currentPathDirections[j] == 'u')
{
j++;
}
if (currentPathDirections[j] == 'a')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'u';
}
}
else if (currentPathDirections[j] == 'b')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'u';
}
}
else if (currentPathDirections[j] == 'l')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'u';
}
}
else if (currentPathDirections[j] == 'r')
{
for (i = 1; i <= currentNodePointer; i++)
{
if (currentPathDirections[i] == 'a')
rotatedPathDirections[i] = 'a';
if (currentPathDirections[i] == 'b')
rotatedPathDirections[i] = 'b';
if (currentPathDirections[i] == 'd')
rotatedPathDirections[i] = 'd';
if (currentPathDirections[i] == 'l')
rotatedPathDirections[i] = 'l';
if (currentPathDirections[i] == 'r')
rotatedPathDirections[i] = 'r';
if (currentPathDirections[i] == 'u')
rotatedPathDirections[i] = 'u';
}
}
}
rotatedPathDirections[currentNodePointer + 1] = '\0';
}
/* Increment the number of paths with this shape. */
if (totalNumberOfShapes == 0)
{
strcpy_s(distinctPathShapes[totalNumberOfShapes], rotatedPathDirections);
/*
numberOfPathsPerShape[totalNumberOfShapes] = 1;
*/
totalNumberOfShapes++;
}
else
{
shapeMatch = false;
for (i_ll = 0; i_ll <= totalNumberOfShapes; i_ll++)
{
if (strcmp(distinctPathShapes[i_ll], rotatedPathDirections) == 0)
{
shapeMatch = true;
/*
numberOfPathsPerShape[i_ll]++;
*/
break;
}
}
if (shapeMatch == false)
{
strcpy_s(distinctPathShapes[totalNumberOfShapes], rotatedPathDirections);
/*
numberOfPathsPerShape[totalNumberOfShapes] = 1;
*/
totalNumberOfShapes++;
}
}
skip_shapes:
/* Increment the number of paths of this length. */
pathLength = currentNodePointer + 1;
numberOfPathsPerLength[pathLength] = numberOfPathsPerLength[pathLength] + 1;
/* Increment the number of paths of this length for the starting node. */
startNodePerLength[currentPath[0]][pathLength] = startNodePerLength[currentPath[0]][pathLength] + 1;
/* Increment the number of paths of this length for the ending node. */
endNodePerLength[currentPath[currentNodePointer]][pathLength] = endNodePerLength[currentPath[currentNodePointer]][pathLength] + 1;
/* Increment the number of paths of this length for each node in the path. */
for (i = 0; i <= currentNodePointer; i++)
{
pathNodePerLength[currentPath[i]][pathLength] = pathNodePerLength[currentPath[i]][pathLength] + 1;
}
/* Determine minimum and maximum path lengths. */
minPathLength = min (minPathLength, pathLength);
maxPathLength = max (maxPathLength, pathLength);
/* Increment the number of paths for each starting-ending node pair. */
startEndNode[currentPath[0]][currentPath[currentNodePointer]] = startEndNode[currentPath[0]][currentPath[currentNodePointer]] + 1;
/* If appropriate, display the path. */
if (outputAllPaths == 'y' || (outputAllPaths == 'n' && currentNodePointer + 1 >= longestCNSAP))
{
longestCNSAP = pathLength;
cout << "Path =";
file << "Path =";
for (i = 0; i <= currentNodePointer; i++)
{
cout << " " << currentPath[i];
file << " " << currentPath[i];
}
cout << "; Length = " << pathLength << endl;
file << "; Length = " << pathLength << endl;
for (i = 1; i <= currentNodePointer; i++)
{
cout << " " << currentPathDirections[i];
file << " " << currentPathDirections[i];
}
cout << endl;
file << endl;
}
/* Construct new CNSAPs until all unused nodes are exhausted. */
anyUnusedNodes = true;
while (anyUnusedNodes == true)
{
if (unusedNodes[currentNodePointer][1] != -1)
{
anyUnusedNodes = false;
currentPath[currentNodePointer] = unusedNodes[currentNodePointer][1];
for (i = 1; i <= nodeNeighbors[currentPath[currentNodePointer - 1]][1]; i++)
{
if (currentPath[currentNodePointer] == nodeNeighbors[currentPath[currentNodePointer - 1]][i + 1])
{
currentPathDirections[currentNodePointer] = nodeNeighborDirections[currentPath[currentNodePointer - 1]][i - 1];
break;
}
}
for (i = 1; i < maxNeighborsPlus3; i++)
{
unusedNodes[currentNodePointer][i] = unusedNodes[currentNodePointer][i + 1];
currentPath[currentNodePointer + i] = -1;
}
}
else
{
/* There are no more neighbors of the current node that we can branch to, so we have to wipe out these nodes from the unusableNodes array */
/* so that neighbors from the next current node can be inserted. */
for (i = 1; i < maxNeighborsPlus3; i++)
{
unusableNodes[currentNodePointer][i] = -1;
}
/* Backtrack to the previous node. */
currentNodePointer--;
}
if (currentNodePointer == 0)
{
finished = true;
anyUnusedNodes = false;
}
}
}
}
if (outputShapeStats == 'y')
{
/* Display the number of paths of each length and shape. */
for (i_ll = 0; i_ll < totalNumberOfShapes; i_ll++)
{
pathLength = strlen(distinctPathShapes[i_ll]); /* Includes initial space to give number of nodes in path. */
numberOfShapesPerLength[pathLength] = numberOfShapesPerLength[pathLength] + 1;
}
file << endl << "Column headings:" << endl;
file << " L = Path Length" << endl;
file << " N = Total number of paths with length L" << endl;
file << " S = Number of different path shapes for each length" << endl << endl;
file << "L N S" << endl;
totalNumberOfPaths = 0;
for (i = minPathLength; i <= maxPathLength; i++)
{
file << i << " " << numberOfPathsPerLength[i] << " " << numberOfShapesPerLength[i] << endl;
totalNumberOfPaths = totalNumberOfPaths + numberOfPathsPerLength[i];
}
file << "Total " << totalNumberOfPaths << " " << totalNumberOfShapes << endl << endl;
/*
file << "Number of times each distinct path shape occurs" << endl;
file << "Shape No. Frequency Shape" << endl;
for (i = 0; i < totalNumberOfShapes; i++)
{
file << i << " " << numberOfPathsPerShape[i] << " " << distinctPathShapes[i] << endl;
}
file << endl;
*/
}
else
{
file << endl << "Column headings:" << endl;
file << " L = Path Length" << endl;
file << " N = Total number of paths with length L" << endl << endl;
file << "L N" << endl;
totalNumberOfPaths = 0;
for (i = minPathLength; i <= maxPathLength; i++)
{
file << i << " " << numberOfPathsPerLength[i] << " " << endl;
totalNumberOfPaths = totalNumberOfPaths + numberOfPathsPerLength[i];
}
file << "Total " << totalNumberOfPaths << " " << endl << endl;
}
file << "Number of times each node is the starting node (SN) in a path of each length (L)" << endl;
file << " SN ";
for (i = 0; i < numberOfNodes; i++)
{
file << i << " ";
}
file << endl;
file << " L" << endl;
for (j = minPathLength; j <= maxPathLength; j++)
{
file << j << " ";
for (i = 0; i < numberOfNodes; i++)
{
file << startNodePerLength[i][j] << " ";
startNode[i] = startNode[i] + startNodePerLength[i][j];
}
file << endl;
}
file << "Total ";
for (i = 0; i < numberOfNodes; i++)
{
file << startNode[i] << " ";
}
file << endl << endl;
file << "Number of times each node is the ending node (EN) in a path of each length (L)" << endl;
file << " EN ";
for (i = 0; i < numberOfNodes; i++)
{
file << i << " ";
}
file << endl;
file << " L" << endl;
for (j = minPathLength; j <= maxPathLength; j++)
{
file << j << " ";
for (i = 0; i < numberOfNodes; i++)
{
file << endNodePerLength[i][j] << " ";
endNode[i] = endNode[i] + endNodePerLength[i][j];
}
file << endl;
}
file << "Total ";
for (i = 0; i < numberOfNodes; i++)
{
file << endNode[i] << " ";
}
file << endl << endl;
file << "Number of times each node (N) is present in a path of each length (L)" << endl;
file << " N ";
for (i = 0; i < numberOfNodes; i++)
{
file << i << " ";
}
file << endl;
file << " L" << endl;
for (j = minPathLength; j <= maxPathLength; j++)
{
file << j << " ";
for (i = 0; i < numberOfNodes; i++)
{
file << pathNodePerLength[i][j] << " ";
pathNode[i] = pathNode[i] + pathNodePerLength[i][j];
}
file << endl;
}
file << "Total ";
for (i = 0; i < numberOfNodes; i++)
{
file << pathNode[i] << " ";
}
file << endl << endl;
file << "Number of paths for each starting node (SN) and ending node (EN) pair" << endl;
file << " SN ";
for (i = 0; i < numberOfNodes; i++)
{
file << i << " ";
}
file << endl;
file << "EN" << endl;
for (j = 0; j < numberOfNodes; j++)
{
file << j << " ";
for (i = 0; i < numberOfNodes; i++)
{
file << startEndNode[i][j] << " ";
}
file << endl;
}
}
cout << endl << "The program is done" << endl;
file << endl << "The program is done" << endl;
goto done;
error:
cout << endl << "Input error: Program terminated" << endl;
file << endl << "Input error: Program terminated" << endl;
done:
file.close();
return 0;
}